<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>五子棋精品版</title>
    <style>
        :root {
            --primary-color: #8B4513;
            --board-color: #E8C192;
            --highlight-color: #F0D4A8;
            --shadow-color: rgba(0, 0, 0, 0.25);
        }
        
        body {
            font-family: 'Arial', sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            overflow: hidden;
        }
        
        .container {
            display: flex;
            flex-direction: column;
            align-items: center;
            max-width: 800px;
            width: 100%;
            padding: 10px;
            box-sizing: border-box;
        }
        
        .game-area {
            display: flex;
            flex-direction: column;
            align-items: center;
            width: 100%;
        }
        
        .canvas-container {
            position: relative;
            margin-bottom: 15px;
        }
        
        canvas {
            display: block;
            box-shadow: 0 8px 24px rgba(0,0,0,0.1);
            border-radius: 5px;
        }
        
        h1 {
            color: #333;
            text-align: center;
            margin-bottom: 20px;
            text-shadow: 1px 1px 3px rgba(0,0,0,0.1);
        }
        
        .status {
            font-size: 1.2em;
            margin: 10px 0;
            padding: 8px 15px;
            background: rgba(255,255,255,0.8);
            border-radius: 20px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.05);
            width: 100%;
            text-align: center;
            transition: all 0.3s ease;
        }
        
        .controls {
            display: flex;
            justify-content: center;
            flex-wrap: wrap;
            gap: 10px;
            margin-top: 10px;
            margin-bottom: 15px;
            width: 100%;
        }
        
        button {
            padding: 10px 20px;
            font-size: 1em;
            background: linear-gradient(to bottom, #6a11cb 0%, #2575fc 100%);
            color: white;
            border: none;
            border-radius: 20px;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 4px 10px rgba(0,0,0,0.1);
            min-width: 100px;
        }
        
        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 15px rgba(0,0,0,0.15);
        }
        
        button:active {
            transform: translateY(1px);
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
        
        button:disabled {
            background: #cccccc;
            cursor: not-allowed;
        }
        
        .black-turn {
            background-color: #333;
            color: white;
        }
        
        .white-turn {
            background-color: #f5f5f5;
            color: #333;
            border: 1px solid #ddd;
        }
        
        .game-over-dialog {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
            z-index: 100;
            text-align: center;
        }
        
        .history-container {
            position: fixed;
            right: 20px;
            top: 20px;
            background: rgba(255, 255, 255, 0.9);
            padding: 10px;
            border-radius: 10px;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
        }
        
        /* 响应式布局 */
        @media (max-width: 600px) {
            .container {
                padding: 5px;
            }
            
            h1 {
                font-size: 1.5em;
            }
            
            .status {
                font-size: 1em;
            }
            
            button {
                padding: 8px 15px;
                font-size: 0.9em;
            }
        }
        
        /* 确保控制按钮在小屏幕上正确显示 */
        @media (max-height: 800px) {
            .container {
                padding-bottom: 60px;
            }
            
            body {
                overflow-y: auto;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>五子棋精品版</h1>
        <div class="game-area">
            <div class="canvas-container">
                <canvas id="gameCanvas" width="450" height="450" tabindex="0" aria-label="五子棋棋盘" role="application"></canvas>
                <div id="currentPositionMarker"></div>
            </div>
            <div class="controls">
                <button id="undoButton" onclick="undoMove()" aria-label="悔棋">悔棋</button>
                <button id="saveButton" onclick="saveGame()" aria-label="保存游戏">保存游戏</button>
                <button id="loadButton" onclick="loadGame()" aria-label="读取游戏">读取游戏</button>
                <button id="restartButton" onclick="resetGame()" aria-label="重新开始">重新开始</button>
            </div>
        </div>
        <div class="status" id="gameInfo">当前轮到黑棋</div>
    </div>
    
    <div id="gameOverDialog" class="game-over-dialog" role="dialog" aria-modal="true" aria-labelledby="gameOverMessage">
        <p id="gameOverMessage"></p>
        <button onclick="resetGame()" aria-label="重新开始游戏">重新开始</button>
    </div>
    
    <div id="moveHistory" class="history-container" style="display: none;">
        <h3>棋局记录</h3>
        <div id="moveList"></div>
    </div>
    
    <!-- 音效资源 (Base64编码，减少HTTP请求) -->
    <audio id="moveSound" preload="auto">
        <source src="data:audio/mpeg;base64,SUQzBAAAAAABEVRYWFgAAAAtAAADY29tbWVudABCaWdTb3VuZEJhbmsuY29tIC8gTGFTb25vdGhlcXVlLm9yZwBURU5DAAAAHQAAA1N3aXRjaCBQbHVzIMKpIE5DSCBTb2Z0d2FyZQBUSVQyAAAABgAAAzIyMzUAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAAAAD/80DEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQsRbAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQMSkAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" type="audio/mpeg">
    </audio>
    <audio id="winSound" preload="auto">
        <source src="data:audio/mpeg;base64,SUQzBAAAAAABEVRYWFgAAAAtAAADY29tbWVudABCaWdTb3VuZEJhbmsuY29tIC8gTGFTb25vdGhlcXVlLm9yZwBURU5DAAAAHQAAA1N3aXRjaCBQbHVzIMKpIE5DSCBTb2Z0d2FyZQBUSVQyAAAABgAAAzIyMzUAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAAAAD/80DEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQsRbAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQMSkAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" type="audio/mpeg">
    </audio>
    <audio id="undoSound" preload="auto">
        <source src="data:audio/mpeg;base64,SUQzBAAAAAABEVRYWFgAAAAtAAADY29tbWVudABCaWdTb3VuZEJhbmsuY29tIC8gTGFTb25vdGhlcXVlLm9yZwBURU5DAAAAHQAAA1N3aXRjaCBQbHVzIMKpIE5DSCBTb2Z0d2FyZQBUSVQyAAAABgAAAzIyMzUAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAAAAD/80DEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQsRbAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQMSkAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" type="audio/mpeg">
    </audio>
    
    <script>
        // 获取DOM元素
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const gameInfo = document.getElementById('gameInfo');
        const gameOverDialog = document.getElementById('gameOverDialog');
        const gameOverMessage = document.getElementById('gameOverMessage');
        const moveSound = document.getElementById('moveSound');
        const winSound = document.getElementById('winSound');
        const undoSound = document.getElementById('undoSound');
        const positionMarker = document.getElementById('currentPositionMarker');
        const moveList = document.getElementById('moveList');
        const undoButton = document.getElementById('undoButton');
        
        // 游戏常量
        const GRID_SIZE = 15; // 15x15的标准棋盘
        let CELL_SIZE = canvas.width / GRID_SIZE;
        const STONE_RADIUS = CELL_SIZE * 0.4; // 棋子半径
        const DIRECTIONS = [
            [1, 0],   // 水平
            [0, 1],   // 垂直
            [1, 1],   // 右下对角线
            [1, -1]   // 右上对角线
        ];
        
        // 游戏状态变量
        let board = Array.from({ length: GRID_SIZE }, () => Array(GRID_SIZE).fill(0));
        let currentPlayer = 1; // 1: 黑棋, -1: 白棋
        let gameOver = false;
        let moveHistory = []; // 记录每一步的落子位置
        let currentPosition = { x: -1, y: -1 }; // 当前光标位置
        let lastMovePosition = null; // 最后落子位置
        let lastMoveTime = 0; // 用于动画效果
        let frameCount = 0;
        let fps = 60;
        let lastFrameTime = 0;
        let particles = []; // 特效粒子
        let isAnimating = false;
        
        // 缓存画布
        let boardCache = null;
        let starPointsCache = null;
        
        // 初始化游戏
        function initGame() {
            // 清空棋盘
            board = Array.from({ length: GRID_SIZE }, () => Array(GRID_SIZE).fill(0));
            currentPlayer = 1;
            gameOver = false;
            moveHistory = [];
            lastMovePosition = null;
            particles = [];
            
            // 重置UI状态
            gameInfo.textContent = "当前轮到黑棋";
            gameInfo.className = "status black-turn";
            gameOverDialog.style.display = "none";
            
            // 禁用悔棋按钮（初始状态无法悔棋）
            undoButton.disabled = true;
            
            // 创建棋盘缓存
            createBoardCache();
            
            // 初始渲染
            requestAnimationFrame(gameLoop);
        }
        
        // 创建棋盘缓存
        function createBoardCache() {
            // 创建棋盘底色缓存
            boardCache = document.createElement('canvas');
            boardCache.width = canvas.width;
            boardCache.height = canvas.height;
            const bctx = boardCache.getContext('2d');
            
            // 绘制棋盘背景（木纹效果）
            const gradient = bctx.createRadialGradient(
                boardCache.width / 2, boardCache.height / 2, 0,
                boardCache.width / 2, boardCache.height / 2, boardCache.width / 1.5
            );
            gradient.addColorStop(0, '#E8C192');
            gradient.addColorStop(1, '#D4A76A');
            
            bctx.fillStyle = gradient;
            bctx.fillRect(0, 0, boardCache.width, boardCache.height);
            
            // 绘制网格线
            bctx.beginPath();
            bctx.strokeStyle = '#8B4513';
            bctx.lineWidth = 1;
            
            // 绘制水平线和垂直线
            for (let i = 0; i < GRID_SIZE; i++) {
                // 水平线
                bctx.moveTo(CELL_SIZE / 2, CELL_SIZE / 2 + i * CELL_SIZE);
                bctx.lineTo(boardCache.width - CELL_SIZE / 2, CELL_SIZE / 2 + i * CELL_SIZE);
                
                // 垂直线
                bctx.moveTo(CELL_SIZE / 2 + i * CELL_SIZE, CELL_SIZE / 2);
                bctx.lineTo(CELL_SIZE / 2 + i * CELL_SIZE, boardCache.height - CELL_SIZE / 2);
            }
            bctx.stroke();
            
            // 创建星位点缓存
            starPointsCache = document.createElement('canvas');
            starPointsCache.width = canvas.width;
            starPointsCache.height = canvas.height;
            const sctx = starPointsCache.getContext('2d');
            
            // 绘制天元和星位
            const starPoints = [
                [3, 3], [3, 7], [3, 11], 
                [7, 3], [7, 7], [7, 11], 
                [11, 3], [11, 7], [11, 11]
            ];
            
            sctx.fillStyle = '#8B4513';
            for (const [x, y] of starPoints) {
                sctx.beginPath();
                sctx.arc(
                    CELL_SIZE / 2 + x * CELL_SIZE, 
                    CELL_SIZE / 2 + y * CELL_SIZE, 
                    CELL_SIZE * 0.1, 
                    0, Math.PI * 2
                );
                sctx.fill();
            }
        }
        
        // 游戏主循环
        function gameLoop(timestamp) {
            // 计算FPS
            if (!lastFrameTime) {
                lastFrameTime = timestamp;
            }
            
            const elapsed = timestamp - lastFrameTime;
            if (elapsed > 1000) {
                fps = Math.round((frameCount * 1000) / elapsed);
                frameCount = 0;
                lastFrameTime = timestamp;
            }
            frameCount++;
            
            // 清除画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            // 绘制棋盘
            drawBoard();
            
            // 绘制棋子
            drawStones();
            
            // 绘制最后一步标记
            if (lastMovePosition) {
                drawLastMoveMarker(lastMovePosition.x, lastMovePosition.y);
            }
            
            // 绘制当前位置指示器（鼠标悬停位置）
            if (!gameOver && currentPosition.x >= 0 && currentPosition.y >= 0) {
                drawPositionIndicator(currentPosition.x, currentPosition.y);
            }
            
            // 更新并绘制粒子效果
            updateParticles();
            drawParticles();
            
            // 请求下一帧
            requestAnimationFrame(gameLoop);
        }
        
        // 绘制棋盘
        function drawBoard() {
            // 使用缓存的棋盘底色
            ctx.drawImage(boardCache, 0, 0);
            
            // 使用缓存的星位点
            ctx.drawImage(starPointsCache, 0, 0);
        }
        
        // 绘制所有棋子
        function drawStones() {
            for (let y = 0; y < GRID_SIZE; y++) {
                for (let x = 0; x < GRID_SIZE; x++) {
                    if (board[y][x] !== 0) {
                        drawStone(x, y, board[y][x]);
                    }
                }
            }
        }
        
        // 绘制单个棋子
        function drawStone(x, y, player) {
            const screenX = CELL_SIZE / 2 + x * CELL_SIZE;
            const screenY = CELL_SIZE / 2 + y * CELL_SIZE;
            const isLastMove = lastMovePosition && lastMovePosition.x === x && lastMovePosition.y === y;
            
            // 棋子阴影
            ctx.beginPath();
            ctx.arc(screenX + 2, screenY + 2, STONE_RADIUS, 0, Math.PI * 2);
            ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
            ctx.fill();
            
            // 棋子本体
            ctx.beginPath();
            ctx.arc(screenX, screenY, STONE_RADIUS, 0, Math.PI * 2);
            
            // 创建棋子渐变
            const gradient = ctx.createRadialGradient(
                screenX - STONE_RADIUS / 3, 
                screenY - STONE_RADIUS / 3, 
                0,
                screenX, 
                screenY, 
                STONE_RADIUS
            );
            
            if (player === 1) { // 黑棋
                gradient.addColorStop(0, '#666');
                gradient.addColorStop(1, '#000');
            } else { // 白棋
                gradient.addColorStop(0, '#fff');
                gradient.addColorStop(1, '#ddd');
            }
            
            ctx.fillStyle = gradient;
            ctx.fill();
            
            // 棋子高光
            ctx.beginPath();
            ctx.arc(
                screenX - STONE_RADIUS / 3, 
                screenY - STONE_RADIUS / 3, 
                STONE_RADIUS / 3, 
                0, Math.PI * 2
            );
            ctx.fillStyle = player === 1 ? 'rgba(255, 255, 255, 0.2)' : 'rgba(255, 255, 255, 0.7)';
            ctx.fill();
            
            // 最后一步动画效果（脉冲环）
            if (isLastMove) {
                const now = performance.now();
                const pulseSize = Math.sin((now - lastMoveTime) / 500) * 0.2 + 0.8;
                
                ctx.beginPath();
                ctx.arc(screenX, screenY, STONE_RADIUS * pulseSize * 1.5, 0, Math.PI * 2);
                ctx.strokeStyle = player === 1 ? 'rgba(255, 255, 255, 0.5)' : 'rgba(0, 0, 0, 0.5)';
                ctx.lineWidth = 2;
                ctx.stroke();
            }
        }
        
        // 绘制最后一步标记
        function drawLastMoveMarker(x, y) {
            const screenX = CELL_SIZE / 2 + x * CELL_SIZE;
            const screenY = CELL_SIZE / 2 + y * CELL_SIZE;
            
            // 十字标记
            ctx.beginPath();
            ctx.strokeStyle = board[y][x] === 1 ? 'rgba(255, 255, 255, 0.8)' : 'rgba(0, 0, 0, 0.8)';
            ctx.lineWidth = 2;
            
            // 水平线
            ctx.moveTo(screenX - STONE_RADIUS / 2, screenY);
            ctx.lineTo(screenX + STONE_RADIUS / 2, screenY);
            
            // 垂直线
            ctx.moveTo(screenX, screenY - STONE_RADIUS / 2);
            ctx.lineTo(screenX, screenY + STONE_RADIUS / 2);
            
            ctx.stroke();
        }
        
        // 绘制当前位置指示器
        function drawPositionIndicator(x, y) {
            const screenX = CELL_SIZE / 2 + x * CELL_SIZE;
            const screenY = CELL_SIZE / 2 + y * CELL_SIZE;
            
            if (board[y][x] === 0) { // 只在空位置显示指示器
                // 半透明的预览棋子
                ctx.beginPath();
                ctx.arc(screenX, screenY, STONE_RADIUS, 0, Math.PI * 2);
                ctx.fillStyle = currentPlayer === 1 ? 'rgba(0, 0, 0, 0.3)' : 'rgba(255, 255, 255, 0.3)';
                ctx.fill();
                
                // 十字准星
                ctx.beginPath();
                ctx.strokeStyle = currentPlayer === 1 ? 'rgba(0, 0, 0, 0.7)' : 'rgba(0, 0, 0, 0.5)';
                ctx.lineWidth = 1;
                
                // 水平线
                ctx.moveTo(screenX - CELL_SIZE / 2, screenY);
                ctx.lineTo(screenX + CELL_SIZE / 2, screenY);
                
                // 垂直线
                ctx.moveTo(screenX, screenY - CELL_SIZE / 2);
                ctx.lineTo(screenX, screenY + CELL_SIZE / 2);
                
                ctx.stroke();
            }
        }
        
        // 粒子系统
        function createParticles(x, y, color, count) {
            const screenX = CELL_SIZE / 2 + x * CELL_SIZE;
            const screenY = CELL_SIZE / 2 + y * CELL_SIZE;
            
            for (let i = 0; i < count; i++) {
                particles.push({
                    x: screenX,
                    y: screenY,
                    size: Math.random() * 3 + 1,
                    color: color,
                    speedX: (Math.random() - 0.5) * 4,
                    speedY: (Math.random() - 0.5) * 4,
                    life: 30
                });
            }
        }
        
        // 更新粒子
        function updateParticles() {
            for (let i = 0; i < particles.length; i++) {
                const p = particles[i];
                p.x += p.speedX;
                p.y += p.speedY;
                p.life--;
                
                if (p.life <= 0) {
                    particles.splice(i, 1);
                    i--;
                }
            }
        }
        
        // 绘制粒子
        function drawParticles() {
            for (const p of particles) {
                ctx.globalAlpha = p.life / 30;
                ctx.fillStyle = p.color;
                ctx.beginPath();
                ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
                ctx.fill();
            }
            ctx.globalAlpha = 1;
        }
        
        // 落子处理
        function placeStone(x, y) {
            // 如果游戏已结束或位置已有棋子，则不允许落子
            if (gameOver || board[y][x] !== 0) {
                return false;
            }
            
            // 落子
            board[y][x] = currentPlayer;
            
            // 记录历史
            moveHistory.push({ x, y, player: currentPlayer });
            
            // 创建落子特效
            createParticles(
                x, y, 
                currentPlayer === 1 ? 'rgba(0, 0, 0, 0.7)' : 'rgba(255, 255, 255, 0.7)', 
                20
            );
            
            // 更新最后落子位置和时间（用于动画）
            lastMovePosition = { x, y };
            lastMoveTime = performance.now();
            
            // 播放落子音效
            moveSound.currentTime = 0;
            moveSound.play().catch(e => console.log('音效播放失败:', e));
            
            // 允许悔棋
            undoButton.disabled = false;
            
            // 检查是否获胜
            if (checkWin(x, y)) {
                gameOver = true;
                const winner = currentPlayer === 1 ? '黑棋' : '白棋';
                gameInfo.textContent = `游戏结束！${winner}获胜！`;
                gameOverMessage.textContent = `${winner}获胜！`;
                gameOverDialog.style.display = 'block';
                
                // 播放胜利音效
                winSound.currentTime = 0;
                winSound.play().catch(e => console.log('音效播放失败:', e));
                
                // 胜利特效
                const color = currentPlayer === 1 ? 'rgba(0, 0, 0, 0.7)' : 'rgba(255, 255, 255, 0.7)';
                for (let i = 0; i < 5; i++) {
                    setTimeout(() => {
                        createParticles(x, y, color, 30);
                    }, i * 200);
                }
                
                return true;
            }
            
            // 切换玩家
            currentPlayer = -currentPlayer;
            
            // 更新状态信息
            if (currentPlayer === 1) {
                gameInfo.textContent = "当前轮到黑棋";
                gameInfo.className = "status black-turn";
            } else {
                gameInfo.textContent = "当前轮到白棋";
                gameInfo.className = "status white-turn";
            }
            
            return true;
        }
        
        // 检查是否获胜
        function checkWin(x, y) {
            const player = board[y][x];
            
            // 检查四个方向
            for (const [dx, dy] of DIRECTIONS) {
                let count = 1; // 当前位置已经有一个棋子
                
                // 沿着方向的正向检查
                for (let i = 1; i < 5; i++) {
                    const nx = x + dx * i;
                    const ny = y + dy * i;
                    
                    if (nx < 0 || nx >= GRID_SIZE || ny < 0 || ny >= GRID_SIZE || board[ny][nx] !== player) {
                        break;
                    }
                    
                    count++;
                }
                
                // 沿着方向的反向检查
                for (let i = 1; i < 5; i++) {
                    const nx = x - dx * i;
                    const ny = y - dy * i;
                    
                    if (nx < 0 || nx >= GRID_SIZE || ny < 0 || ny >= GRID_SIZE || board[ny][nx] !== player) {
                        break;
                    }
                    
                    count++;
                }
                
                // 如果连成5个或更多，则获胜
                if (count >= 5) {
                    return true;
                }
            }
            
            return false;
        }
        
        // 悔棋功能
        function undoMove() {
            if (moveHistory.length === 0 || gameOver) {
                return;
            }
            
            // 移除最后一步
            const lastMove = moveHistory.pop();
            board[lastMove.y][lastMove.x] = 0;
            
            // 恢复当前玩家
            currentPlayer = lastMove.player;
            
            // 更新最后落子位置
            lastMovePosition = moveHistory.length > 0 ? 
                { x: moveHistory[moveHistory.length - 1].x, y: moveHistory[moveHistory.length - 1].y } : null;
            
            // 更新状态信息
            if (currentPlayer === 1) {
                gameInfo.textContent = "当前轮到黑棋";
                gameInfo.className = "status black-turn";
            } else {
                gameInfo.textContent = "当前轮到白棋";
                gameInfo.className = "status white-turn";
            }
            
            // 如果没有历史记录，禁用悔棋按钮
            if (moveHistory.length === 0) {
                undoButton.disabled = true;
            }
            
            // 播放悔棋音效
            undoSound.currentTime = 0;
            undoSound.play().catch(e => console.log('音效播放失败:', e));
        }
        
        // 重置游戏
        function resetGame() {
            initGame();
        }
        
        // 保存游戏
        function saveGame() {
            const gameData = {
                board: board,
                currentPlayer: currentPlayer,
                moveHistory: moveHistory
            };
            
            localStorage.setItem('gomokuGameSave', JSON.stringify(gameData));
            alert('游戏已保存');
        }
        
        // 读取游戏
        function loadGame() {
            const savedData = localStorage.getItem('gomokuGameSave');
            
            if (!savedData) {
                alert('没有找到保存的游戏');
                return;
            }
            
            try {
                const gameData = JSON.parse(savedData);
                
                // 恢复游戏状态
                board = gameData.board;
                currentPlayer = gameData.currentPlayer;
                moveHistory = gameData.moveHistory;
                
                // 更新UI
                if (moveHistory.length > 0) {
                    const lastMove = moveHistory[moveHistory.length - 1];
                    lastMovePosition = { x: lastMove.x, y: lastMove.y };
                    lastMoveTime = performance.now();
                    undoButton.disabled = false;
                } else {
                    lastMovePosition = null;
                    undoButton.disabled = true;
                }
                
                // 更新状态信息
                if (currentPlayer === 1) {
                    gameInfo.textContent = "当前轮到黑棋";
                    gameInfo.className = "status black-turn";
                } else {
                    gameInfo.textContent = "当前轮到白棋";
                    gameInfo.className = "status white-turn";
                }
                
                gameOver = false;
                gameOverDialog.style.display = "none";
                
                alert('游戏已加载');
            } catch (e) {
                console.error('加载游戏失败:', e);
                alert('加载游戏失败');
            }
        }
        
        // 事件处理
        function handleCanvasClick(event) {
            if (gameOver) return;
            
            const rect = canvas.getBoundingClientRect();
            const x = event.clientX - rect.left;
            const y = event.clientY - rect.top;
            
            // 将屏幕坐标转换为棋盘格坐标
            const gridX = Math.floor(x / CELL_SIZE);
            const gridY = Math.floor(y / CELL_SIZE);
            
            // 确保坐标在有效范围内
            if (gridX >= 0 && gridX < GRID_SIZE && gridY >= 0 && gridY < GRID_SIZE) {
                placeStone(gridX, gridY);
            }
        }
        
        function handleCanvasMouseMove(event) {
            const rect = canvas.getBoundingClientRect();
            const x = event.clientX - rect.left;
            const y = event.clientY - rect.top;
            
            // 将屏幕坐标转换为棋盘格坐标
            const gridX = Math.floor(x / CELL_SIZE);
            const gridY = Math.floor(y / CELL_SIZE);
            
            // 确保坐标在有效范围内
            if (gridX >= 0 && gridX < GRID_SIZE && gridY >= 0 && gridY < GRID_SIZE) {
                currentPosition = { x: gridX, y: gridY };
            } else {
                currentPosition = { x: -1, y: -1 };
            }
        }
        
        function handleCanvasMouseLeave() {
            currentPosition = { x: -1, y: -1 };
        }
        
        // 键盘控制
        function handleKeyDown(event) {
            if (gameOver) return;
            
            // 如果当前位置不在棋盘上，初始化为中心位置
            if (currentPosition.x < 0 || currentPosition.y < 0) {
                currentPosition = { x: Math.floor(GRID_SIZE / 2), y: Math.floor(GRID_SIZE / 2) };
                return;
            }
            
            switch (event.key) {
                case 'ArrowUp':
                    if (currentPosition.y > 0) {
                        currentPosition.y--;
                    }
                    event.preventDefault();
                    break;
                case 'ArrowDown':
                    if (currentPosition.y < GRID_SIZE - 1) {
                        currentPosition.y++;
                    }
                    event.preventDefault();
                    break;
                case 'ArrowLeft':
                    if (currentPosition.x > 0) {
                        currentPosition.x--;
                    }
                    event.preventDefault();
                    break;
                case 'ArrowRight':
                    if (currentPosition.x < GRID_SIZE - 1) {
                        currentPosition.x++;
                    }
                    event.preventDefault();
                    break;
                case 'Enter':
                case ' ':
                    // 落子
                    placeStone(currentPosition.x, currentPosition.y);
                    event.preventDefault();
                    break;
                case 'z':
                    // 如果按住Ctrl/Command键，执行悔棋
                    if (event.ctrlKey || event.metaKey) {
                        undoMove();
                        event.preventDefault();
                    }
                    break;
            }
        }
        
        // 添加事件监听器
        function addEventListeners() {
            canvas.addEventListener('click', handleCanvasClick);
            canvas.addEventListener('mousemove', handleCanvasMouseMove);
            canvas.addEventListener('mouseleave', handleCanvasMouseLeave);
            canvas.addEventListener('keydown', handleKeyDown);
            
            // 移动端触摸支持
            canvas.addEventListener('touchstart', function(e) {
                e.preventDefault();
                const touch = e.touches[0];
                const mouseEvent = new MouseEvent('click', {
                    clientX: touch.clientX,
                    clientY: touch.clientY
                });
                canvas.dispatchEvent(mouseEvent);
            });
        }
        
        // 移动设备适配
        function resizeCanvas() {
            const maxWidth = window.innerWidth - 20;
            const maxHeight = window.innerHeight - 200;
            const size = Math.min(maxWidth, maxHeight, 600);
            
            canvas.width = size;
            canvas.height = size;
            
            // 更新单元格大小
            CELL_SIZE = canvas.width / GRID_SIZE;
            
            // 重新渲染游戏
            initGame();
        }
        
        // 注册窗口调整大小事件
        window.addEventListener('resize', resizeCanvas);
        
        // 初始化游戏
        window.onload = function() {
            // 检测移动设备并调整尺寸
            resizeCanvas();
            
            // 添加事件监听器
            addEventListeners();
            
            // 启动游戏
            initGame();
        };
    </script>
</body>
</html>